package com.zjcode.oa.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chinatechstar.component.commons.controller.BaseController;
import com.chinatechstar.component.commons.result.ListResult;
import com.chinatechstar.component.commons.result.ResultBuilder;
import com.chinatechstar.component.commons.supports.PageData;
import com.zjcode.oa.config.MConsts;
import com.zjcode.oa.model.JsonObj;
import com.zjcode.oa.model.OaJournalAttachment;
import com.zjcode.oa.model.OaProjectInfo;
import com.zjcode.oa.model.OaProjectJournal;
import com.zjcode.oa.model.ZjcodeSysUser;
import com.zjcode.oa.service.OaProjectInfoService;
import com.zjcode.oa.service.ProjectJournalService;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * @ClassName:OaController
 * @功能：
 * @author：wlei
 * @日期：2022/4/8-4:52 PM
 **/
@RestController
@Slf4j
@RequestMapping("/v1/oa/")
public class OaController extends BaseController {

    @Autowired
    private ProjectJournalService projectJournalService;
    @Autowired
    private OaProjectInfoService projectInfoService;
    @Value("${studio.image-upload-dir}")
    private String imageUploadDir;
    @Value("${studio.image-server-baseurl}")
    private String imageServerBaseurl;


    @RequestMapping("version")
    public JsonObj version(HttpServletRequest request) {
        int serverPort = request.getServerPort();
        Map<String, Object> data = new HashMap<>();
        data.put("version", "1.0.0");
        data.put("serverPort", serverPort);
        JsonObj success = JsonObj.success(data);
        return success;
    }

    /**
     * 分页获取日志数据
     *
     * @return
     */
    @GetMapping("listJournalsByPage")
    public ListResult<Object> listJournalsByPage() {
        Map<String, Object> map = projectJournalService.listByPage(getPageData());
        return ResultBuilder.buildListSuccess(map);
    }

    /**
     * 获取所有的已知项目
     *
     * @return
     */
    @RequestMapping("queryAllProjects")
    public JsonObj queryAllProjects() {
        List<OaProjectInfo> oaProjectInfos = projectInfoService.selectAll();
        Map<String, Object> data = new HashMap<>();
        data.put("projects", oaProjectInfos);
        return JsonObj.success(data);
    }

    @RequestMapping("createProjectJournal")
    public JsonObj createProjectJournal() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        PageData pd = getPageData();

        OaProjectJournal journal = new OaProjectJournal();
        journal.setProjectId((String) pd.get("project_id"));
        try {
            journal.setRecordDatetime(sdf.parse((String) pd.get("record_datetime")));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        journal.setRemarks((String) pd.get("remarks"));
        journal.setNextplan((String) pd.get("nextplan"));
        journal.setCreateBy((String) pd.get("create_by"));
        journal.setCreateTime(new Date(System.currentTimeMillis()));
        journal.setUpdateTime(new Date(System.currentTimeMillis()));
        journal.setIsDelete(0);
        journal.setId(get32UUID());

        int insert = projectJournalService.insert(journal);

        // 获取附件信息
        String attachment = (String) pd.get("attachment");
        JSONArray array = JSONObject.parseArray(attachment);
        if (!array.isEmpty()) {
            // 写入附件
            List<OaJournalAttachment> attachments = array
                .stream()
                .map(o -> {
                    JSONObject jo = (JSONObject) o;
                    String filename = jo.getString("filename");
                    String url = jo.getString("url");
                    OaJournalAttachment journalAttachment = getJournalAttachment(journal,
                                                                                 filename,
                                                                                 url);
                    return journalAttachment;
                })
                .collect(Collectors.toList());
            // 执行数据库写入操作
            projectJournalService.insertAttachments(attachments);
        }

        if (insert > 0) {
            return JsonObj.success("日志创建成功");
        }
        return JsonObj.error("创建失败,请联系管理员");
    }

    /**
     * 获取所有的开发人员
     *
     * @return
     */
    @RequestMapping("selectAllDevelopers")
    public JsonObj selectAllDevelopers() {
        List<ZjcodeSysUser> developers = projectJournalService.selectAllDevelopers();
        Map<String, Object> map = new HashMap<>();
        // 用户密码脱敏
        developers
            .parallelStream()
            .forEach(zjcodeSysUser -> zjcodeSysUser.setPassword("***"));
        map.put("developers", developers);
        return JsonObj.success(map);
    }

    /**
     * 按照用户获取对应的日志信息
     *
     * @return
     */
    @RequestMapping("selectAllJournalsByUser")
    public JsonObj selectAllJournalsBy() {
        PageData pageData = getPageData();
        String create_by = (String) pageData.get("create_by");
        String search_date = (String) pageData.get("search_date");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        LocalDate now = LocalDate.now();

        try {
            Date date = sdf.parse(search_date);
            Instant instant = date.toInstant();
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
            now = localDateTime.toLocalDate();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // 最后一天
        String end = getLastDayOfMonth(now);
        // 第一天
        String start = getLastMonthFirstDayOfMonth(now);

        List<OaProjectJournal> journals = new ArrayList<>();
        try {
            journals.addAll(projectJournalService.selectAllJournalBy(sdf.parse(start),
                                                                     sdf.parse(end),
                                                                     create_by));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // 将附件信息解析出来
        parseAttachment(journals);

        // 按照日期进行分组
        Map<String, List<OaProjectJournal>> map = journals
            .stream()
            .collect(Collectors.groupingBy(oaProjectJournal -> {
                Date recordDatetime = oaProjectJournal.getRecordDatetime();
                Instant instant = recordDatetime.toInstant();
                ZoneId zone = ZoneId.systemDefault();
                LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
                int dayOfMonth = localDateTime.getDayOfMonth();
                return String.valueOf(dayOfMonth);
            }));

        Map<String, Object> data = new HashMap<>();
        data.put("journals", map);
        return JsonObj.success(data);
    }

    /**
     * 删除日志
     *
     * @return
     */
    @RequestMapping("deleteJournalById")
    public JsonObj deleteJournalById() {
        PageData pd = getPageData();
        String id = (String) pd.get("id");
        int delCount = projectJournalService.delById(id);
        if (delCount == -1) {
            return JsonObj.error("日志无法删除,请联系管理员");
        }
        return JsonObj.success("日志删除成功");
    }

    /**
     * 文件上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping(value = "uploadJournalFile", consumes = {"multipart/form-data"})
    public ListResult<Object> uploadJournalFile(@RequestParam(name = "file", required = true) MultipartFile file)
        throws IOException {
        PageData pd = this.getPageData();
        String username = (String) pd.get("username");
        log.info("附件存放地址:" + imageUploadDir);
        log.info("url地址:" + imageServerBaseurl);

        String originalFilename = file.getOriginalFilename();
        // 生成动态文件名
        String fileName =
            DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + "_" + originalFilename;

        // 将文件写入磁盘
        saveFile2Disk(file, generatePath(fileName, username));

        // 图片访问地址
        String url = imageServerBaseurl + username + "/" + fileName;
        log.info("图片访问地址:" + url);

        Map<String, Object> data = new HashMap<>();
        data.put("msg", "上传成功");
        data.put("url", url);
        data.put("filename", originalFilename);
        return ResultBuilder.buildListSuccess(data);
    }

    /**
     * 解析出日志中的附件信息
     *
     * @param journals
     */
    private void parseAttachment(List<OaProjectJournal> journals) {
        journals
            .parallelStream()
            .forEach(oaProjectJournal -> {
                String filenames = oaProjectJournal.getFilenames();
                String filepaths = oaProjectJournal.getFilepaths();
                String attachmentsids = oaProjectJournal.getAttachmentsids();
                // 对是否允许拆分进行判断
                if (attachmentsids != null) {
                    String[] ids = attachmentsids.split(MConsts.STRING_SEPARATOR);
                    String[] names = filenames.split(MConsts.STRING_SEPARATOR);
                    String[] paths = filepaths.split(MConsts.STRING_SEPARATOR);

                    List<String> list = Arrays.asList(ids);

                    AtomicInteger index = new AtomicInteger();
                    List<OaJournalAttachment> attachments = list
                        .stream()
                        .map(id -> {
                            OaJournalAttachment oaJournalAttachment = getJournalAttachment(names,
                                                                                           paths,
                                                                                           index,
                                                                                           id);
                            index.getAndIncrement();
                            return oaJournalAttachment;
                        })
                        .collect(Collectors.toList());

                    oaProjectJournal.setAttachments(attachments);
                } else {
                    oaProjectJournal.setAttachments(null);
                }
            });
    }

    /**
     * 获取附件对象
     *
     * @param names
     * @param paths
     * @param index
     * @param id
     * @return
     */
    private OaJournalAttachment getJournalAttachment(String[] names,
                                                     String[] paths,
                                                     AtomicInteger index,
                                                     String id) {
        OaJournalAttachment oaJournalAttachment = new OaJournalAttachment();
        oaJournalAttachment.setId(Integer.parseInt(id));
        oaJournalAttachment.setFileName(names[index.get()]);
        oaJournalAttachment.setFilePath(paths[index.get()]);
        return oaJournalAttachment;
    }

    /**
     * 获取日志附件对象
     *
     * @param journal
     * @param filename
     * @param url
     * @return
     */
    private OaJournalAttachment getJournalAttachment(OaProjectJournal journal,
                                                     String filename,
                                                     String url) {
        OaJournalAttachment journalAttachment = new OaJournalAttachment();
        journalAttachment.setJournalId(journal.getId());
        journalAttachment.setFileName(filename);
        journalAttachment.setFilePath(url);
        journalAttachment.setCreatTime(new Date(System.currentTimeMillis()));
        journalAttachment.setUpdateTime(new Date(System.currentTimeMillis()));
        journalAttachment.setCreateBy("");
        journalAttachment.setIsDelete(0);
        return journalAttachment;
    }

    /**
     * 返回当前月份的最后一天
     *
     * @return
     */
    private String getLastDayOfMonth(LocalDate localDate) {
        LocalDate lastDay = localDate.with(TemporalAdjusters.lastDayOfMonth());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String format = formatter.format(lastDay);
        return format;
    }

    /**
     * 获取一个月的第一天
     *
     * @return
     */
    private String getLastMonthFirstDayOfMonth(LocalDate localDate) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate ld = localDate.with(TemporalAdjusters.firstDayOfMonth());
        String format = formatter.format(ld);
        return format;
    }

    /**
     * 将文件写入磁盘
     *
     * @param file
     * @param path
     * @throws IOException
     */
    private void saveFile2Disk(MultipartFile file, String path) throws IOException {
        File f = new File(path);
        if (f.exists()) {
            f.delete();
        }
        // 创建文件夹
        f
            .getParentFile()
            .mkdirs();

        //将文件写入磁盘
        Files.write(Paths
                        .get(path)
                        .normalize()
                        .toAbsolutePath(), file.getBytes(), StandardOpenOption.CREATE_NEW);
    }

    /**
     * 上传文件到与jar包同级的外部目录
     *
     * @param fileName 已修改成时间戳的文件名称
     * @param username 文件所属用户的名称
     * @return
     * @throws IOException
     */
    private String generatePath(String fileName, String username) throws IOException {
        return imageUploadDir + username + "/" + fileName;
    }

}
